﻿Imports System.IO.IsolatedStorage
Imports Runa.Common.Helper
Imports Runa.Foundation.IO
Imports System.IO

#If WINDOWS_PHONE Then
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
#ElseIf WINDOWS Then
Imports System.Drawing
#End If

Namespace Global.Runa.Core.GamePackage

    ''' <summary>
    ''' Extractor for extracting the game package (*.zip stored in DownloadedGames).
    ''' </summary>
    ''' <remarks></remarks>
    Public MustInherit Class GamePackageBase
        Implements IDisposable

        Public Property Name() As String
        Public Property Author() As String
        Public Property Fps() As Integer = 333333
        Public Property GPUAccelerationEnabled() As Boolean = False

#If WINDOWS_PHONE Then
        Public Property Image() As BitmapImage
        Public Property Orientation() As String
#ElseIf WINDOWS Then

#If NETFX_CORE Then
        Public Property Image() As Byte()

        Public ReadOnly Property BitmapImage() As BitmapImage
            Get
                Dim bmp As New BitmapImage()
                bmp.FromBytes(Me.Image)
                Return bmp
            End Get
        End Property
#Else
        Public Property Image() As System.Drawing.Bitmap
        Public Property IsFullScreen() As Boolean
        Public Property WindowHeight() As Integer
        Public Property WindowWidth() As Integer
#End If

        Public Property MouseSensitive() As Integer
#End If

        Public Property PhysicalStorage() As GameDirectory
        Public Property GameContentRoot() As String

        Protected m_imageStream As Stream

        ''' <summary>
        ''' By default, our package should be strored in the IsolatedStorage.
        ''' </summary>
        ''' <param name="gamePackageFileName">The file name of the package.</param>
        ''' <remarks></remarks>
        Public Sub New(ByVal gamePackageFileName As String)
            Me.New(gamePackageFileName, New IsolatedFileStorageGameDirectory())
        End Sub

        ''' <summary>
        ''' By default, our package should be strored in the IsolatedStorage.
        ''' But we can also store in other places like file system.
        ''' </summary>
        ''' <param name="gamePackageFileName"></param>
        ''' <param name="physicalStorage"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal gamePackageFileName As String, ByVal physicalStorage As GameDirectory)
            Me.PhysicalStorage = physicalStorage
            Dim files = Me.PhysicalStorage.GetFiles()
            If files.LongCount(
                Function(item)
                    Dim ext = Path.GetExtension(item).ToLower()
                    Return Path.GetFileNameWithoutExtension(item).ToLower() =
                        Path.GetFileNameWithoutExtension(gamePackageFileName).ToLower() And
                        ext = ".zip"
                End Function) > 0 Then
                Me.GameContentRoot = Path.GetFileNameWithoutExtension(gamePackageFileName)
                While True
                    If Me.PhysicalStorage.DirectoryExists(Me.GameContentRoot) Then
                        Call AnalyzeConfigurationFile()
                        Exit While
                    Else
                        Me.ExtractGamePackage(gamePackageFileName)
                        Continue While
                    End If
                End While
            Else
                Throw New FileNotFoundException(String.Format("File {0} not found in the IsolatedStorage.", gamePackageFileName))
            End If
        End Sub

        ''' <summary>
        ''' Save and extract a package from a stream.
        ''' </summary>
        ''' <param name="gameName"></param>
        ''' <param name="packageStream"></param>
        ''' <param name="physicalStorage"></param>
        ''' <remarks>
        ''' Make sure that the stream is a non-network stream to gain better performance and stability.
        ''' </remarks>
        Public Sub New(ByVal gameName As String, ByVal packageStream As Stream, Optional ByVal physicalStorage As GameDirectory = Nothing)
            Me.PhysicalStorage = If(physicalStorage, New IsolatedFileStorageGameDirectory())
            Me.GameContentRoot = gameName
            Me.ExtractFromStream(packageStream)
            Call AnalyzeConfigurationFile()
        End Sub

        ''' <summary>
        ''' Analyze the configuration file of the game.
        ''' </summary>
        ''' <remarks></remarks>
        Public MustOverride Sub AnalyzeConfigurationFile()

        ''' <summary>
        ''' Extract the zip package stored in the IsolatedStorage.
        ''' </summary>
        ''' <param name="strPackageFileName">The package name is the same as game name.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function ExtractGamePackage(ByVal strPackageFileName As String) As Boolean
            Try
                Using fs = Me.PhysicalStorage.OpenFile(strPackageFileName, Runa.Foundation.IO.FileMode.Open)
                    Return Me.ExtractFromStream(fs)
                End Using
            Catch ex As Exception
#If DEBUG Then
                Throw ex
#End If
                Return False
            End Try
        End Function

        ''' <summary>
        ''' Extract the game package from a stream.
        ''' </summary>
        ''' <param name="packageStream"></param>
        ''' <remarks></remarks>
        Public MustOverride Function ExtractFromStream(ByVal packageStream As Stream) As Boolean

        Public Overrides Function ToString() As String
            Return Me.Name
        End Function

#Region "IDisposable Support"
        Private disposedValue As Boolean ' To detect redundant calls

        ' IDisposable
        Protected Overridable Sub Dispose(disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                    ' TODO: dispose managed state (managed objects).
                End If
                ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
                ' TODO: set large fields to null.
                Me.m_imageStream.Close()
                Me.m_imageStream.Dispose()
                Me.m_imageStream = Nothing
            End If
            Me.disposedValue = True
        End Sub

        ' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
        'Protected Overrides Sub Finalize()
        '    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        '    Dispose(False)
        '    MyBase.Finalize()
        'End Sub

        ' This code added by Visual Basic to correctly implement the disposable pattern.
        Public Sub Dispose() Implements IDisposable.Dispose
            ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
#End Region

    End Class

End Namespace